package com.pxx.pj.pxx.service.impl;


import com.pxx.pj.common.annotation.RequiredCache;
import com.pxx.pj.common.annotation.RequiredLog;
import com.pxx.pj.common.pojo.PageObject;
import com.pxx.pj.common.util.ValidUitls;
import com.pxx.pj.pxx.dao.PxxMenuDao;
import com.pxx.pj.pxx.dao.PxxRoleMenuDao;
import com.pxx.pj.pxx.dao.PxxUserDao;
import com.pxx.pj.pxx.dao.PxxUserRoleDao;
import com.pxx.pj.pxx.pojo.PxxDepts;
import com.pxx.pj.pxx.pojo.PxxUser;
import com.pxx.pj.pxx.pojo.PxxUserDept;
import com.pxx.pj.pxx.pojo.PxxUserMenu;
import com.pxx.pj.pxx.service.PxxUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Transactional(readOnly = false,
                rollbackFor = Throwable.class,
                timeout = 60,
                isolation = Isolation.READ_COMMITTED,
                propagation = Propagation.REQUIRED
                )
@Service
public class PxxUserServiceImpl  implements PxxUserService {
    @Autowired
    private PxxUserDao pxxUserDao;

    @Autowired
    private PxxUserRoleDao pxxUserRoleDao;

    @Autowired
    private PxxMenuDao pxxMenuDao;
    @Autowired
    private PxxRoleMenuDao pxxRoleMenuDao;
    @Override
    public List<PxxUserMenu> findUserMenusByUserId(Integer id) {
        //1.对用户id进行判断
        //2.基于用户id查找用户对应的角色id
        List<Integer> roleIds=
                pxxUserRoleDao.findRoleIdsByUserId(id);
        //3.基于角色id获取角色对应的菜单信息,并进行封装.
        List<Integer> menuIds=
                pxxRoleMenuDao.findMenuIdsByRoleIds(roleIds);
        //4.基于菜单id获取用户对应的菜单信息并返回
        return pxxMenuDao.findMenusByIds(menuIds);
    }

    @Override
    public int updatePassword(String newPassword, String cfgPassword, String sourcePassword) {
        //校验参数
        ValidUitls.isArgsValid(StringUtils.isEmpty(sourcePassword),"原密码不能为空");
        ValidUitls.isResultValid(newPassword==null||"".equals(newPassword),"新密码不能为空");
        ValidUitls.isArgsValid(!newPassword.equals(cfgPassword),"两次密码不一致");
        //验证原密码是否正确
        PxxUser user=(PxxUser) SecurityUtils.getSubject().getPrincipal();
        SimpleHash sh=new SimpleHash("MD5",sourcePassword,user.getSalt(),1);
        ValidUitls.isArgsValid(!user.getPassword().equals(sh.toHex()),"原密码不正确");
        //修改密码
        String newSalt= UUID.randomUUID().toString();
        sh=new SimpleHash("MD5",newPassword,newSalt,1);

        String newHashedPassword=sh.toHex();
        int rows=pxxUserDao.updatePassword(user.getUsername(), newHashedPassword, newSalt);
        ValidUitls.isResultValid(rows==0, "记录不存在");

        return rows;
    }



    @Override
    public int updateObject(PxxUser entity, Integer[] roleIds) {
        ValidUitls.isArgsValid(entity==null, "保存对象不能为空");
        ValidUitls.isArgsValid(StringUtils.isEmpty(entity.getUsername()), "用户名不能为空");
        ValidUitls.isArgsValid(roleIds==null||roleIds.length==0, "必须为其指定角色");
        int rows=pxxUserDao.updateObject(entity);
        pxxUserRoleDao.deleteObjectsByUserId(entity.getId());
        pxxUserRoleDao.insertObjects(entity.getId(), roleIds);
        return rows;


    }


    @Transactional(readOnly = true)
    @RequiredLog("查询用户")
    @Override
    public Map<String, Object> findObjectById(Integer userId) {
        ValidUitls.isArgsValid(userId==null||userId<=0,"参数不合法" );
        PxxUserDept user=pxxUserDao.findObjectById(userId);
        ValidUitls.isResultValid(user==null, "此用户已经不存在");

        List<Integer> roleIds=pxxUserRoleDao.findRoleIdsByUserId(userId);
        //3.数据封装
        Map<String ,Object> map=new HashMap<>();
        map.put("user", user);
        map.put("roleIds", roleIds);
        return map;



    }

    @Override
    @RequiresPermissions("sys:user:update")
    public int saveObject(PxxUser entity, Integer[] roleIds) {
        //1.参数校验
        ValidUitls.isArgsValid(entity==null,"保存对象不能为空");
        ValidUitls.isArgsValid(StringUtils.isEmpty((entity.getUsername())), "用户名不能为空");
        ValidUitls.isArgsValid(StringUtils.isEmpty(entity.getPassword()),"密码不能为空");
        ValidUitls.isArgsValid(roleIds==null||roleIds.length==0, "至少要为用户分配角色");
        //2.保存用户自身信息
        //2.1对密码进行加密
        String password=entity.getPassword();
        String salt= UUID.randomUUID().toString();//产生随机字符，让此字符串作为一个加密盐值,
        //Shiro框架
        //将盐值和密码存储到entity对象

        SimpleHash sh=new SimpleHash("MD5"//algorithmName 算法
                ,password,//原密码 对谁加密
                salt, //盐值 随机字符串
                1);//hashIterations表示加密次数
        String newPwd=sh.toHex();
        entity.setSalt(salt);
        entity.setPassword(newPwd);
        int rows=pxxUserDao.insertObject(entity);
        pxxUserRoleDao.insertObjects(entity.getId(), roleIds);

        return rows;

    }

    @Override
    @RequiresPermissions("sys:user:update")
    public int validById(Integer id, Integer valid) {
        ValidUitls.isResultValid(id==null||id<=0, "参数不合法,id="+id);
        ValidUitls.isResultValid(valid==null||(valid!=1&&valid!=0),"参数不合法，valid="+valid );
        int rows=pxxUserDao.validById(id, valid, "admin");
        ValidUitls.isResultValid(rows==0, "此记录可能已经不存在");
        return rows;
    }

    @Override
    public PageObject<PxxUserDept> findPageObjects(String username, Integer pageCurrent) {
        ValidUitls.isArgsValid(pageCurrent==null||pageCurrent<1, "当前页码值不正确");
        int rowCount=pxxUserDao.getRowCount(username);
        ValidUitls.isResultValid(rowCount==0, "没有找到对应记录");
        int pageSize=5;
        int startIndex=(pageCurrent-1)*pageSize;
        List<PxxDepts> records=pxxUserDao.findPageObjects(username, startIndex, pageSize);


        return new PageObject(rowCount,records,pageCurrent,pageSize);
    }

    }

